﻿// -----------------------------------------------------------------------
// <copyright file="ColumnDto.cs" company="JSC Centido">
//  Copyright (c) JSC Centido. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

using System;

namespace Centido.Core.Dto
{
    /// <summary>
    ///   A data transfer object for a table column.
    /// </summary>
    public abstract class ColumnDto : DataTransferObject
    {
        /// <summary>
        ///   The name of the xml attribute that is used to store a column name.
        /// </summary>
        public const string NameAttribute = "name";

        /// <summary>
        ///   The name of the xml attribute that is used to store a column display name.
        /// </summary>
        public const string DisplayNameAttribute = "displayName";

        /// <summary>
        ///   The name of the xml attribute that is used to store a column description.
        /// </summary>
        public const string DescriptionAttribute = "description";

        /// <summary>
        ///   The name of the xml attribute that is used to store a column order index.
        /// </summary>
        public const string OrderIndexAttribute = "order";

        /// <summary>
        ///   The name of the xml attribute that is used to store a column nullability.
        /// </summary>
        public const string IsNotNullAttribute = "notNull";

        /// <summary>
        ///   Gets or sets the name of the column.
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        ///   Gets or sets the display name of the column.
        /// </summary>
        public string DisplayName { get; set; }

        /// <summary>
        ///   Gets or sets the description of the column.
        /// </summary>
        public string Description { get; set; }

        /// <summary>
        ///   Gets or sets the order index of the column.
        /// </summary>
        public int? OrderIndex { get; set; }

        /// <summary>
        ///   Gets or sets the nullability of the column.
        /// </summary>
        public bool? IsNotNull { get; set; }

        /// <summary>
        ///   Gets the column type.
        /// </summary>
        public abstract ColumnType ColumnType { get; }


        /// <summary>
        ///   Checks that the specified string value is an xml tag for one of the table column types.
        /// </summary>
        /// <param name="xmlTag">The specified string value.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="xmlTag"/> is null.</exception>
        /// <returns>Returns true if the specified string is an xml tag for one of the table column types.</returns>
        public static bool IsColumnTag(string xmlTag)
        {
            if (xmlTag == null)
                throw new ArgumentNullException("xmlTag");

            switch (xmlTag)
            {
                case EnumColumnDto.XmlTag:
                    return true;
                case RefColumnDto.XmlTag:
                    return true;
                case BigIntColumnDto.XmlTag:
                    return true;
                case BinaryColumnDto.XmlTag:
                    return true;
                case BoolColumnDto.XmlTag:
                    return true;
                case DateTimeColumnDto.XmlTag:
                    return true;
                case DecimalColumnDto.XmlTag:
                    return true;
                case GuidColumnDto.XmlTag:
                    return true;
                case IntColumnDto.XmlTag:
                    return true;
                case SmallIntColumnDto.XmlTag:
                    return true;
                case StringColumnDto.XmlTag:
                    return true;
                case TextColumnDto.XmlTag:
                    return true;
                default:
                    return false;
            }
        }


        /// <summary>
        ///   Creates a new data transfer object for the specified column type.
        /// </summary>
        /// <param name="xmlTag">The xml tag for the new column data transfer object
        /// that specifies the column type.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="xmlTag"/> is null.</exception>
        /// <returns>Returns the new data transfer object for the specified column type.</returns>
        public static ColumnDto CreateNew(string xmlTag)
        {
            if (xmlTag == null)
                throw new ArgumentNullException("xmlTag");

            switch (xmlTag)
            {
                case EnumColumnDto.XmlTag:
                    return new EnumColumnDto();
                case RefColumnDto.XmlTag:
                    return new RefColumnDto();
                case BigIntColumnDto.XmlTag:
                    return new BigIntColumnDto();
                case BinaryColumnDto.XmlTag:
                    return new BinaryColumnDto();
                case BoolColumnDto.XmlTag:
                    return new BoolColumnDto();
                case DateTimeColumnDto.XmlTag:
                    return new DateTimeColumnDto();
                case DecimalColumnDto.XmlTag:
                    return new DecimalColumnDto();
                case GuidColumnDto.XmlTag:
                    return new GuidColumnDto();
                case IntColumnDto.XmlTag:
                    return new IntColumnDto();
                case SmallIntColumnDto.XmlTag:
                    return new SmallIntColumnDto();
                case StringColumnDto.XmlTag:
                    return new StringColumnDto();
                case TextColumnDto.XmlTag:
                    return new TextColumnDto();
                default:
                    throw new ArgumentException("The specified xml tag does not correspond to any column type.");
            }
        }


        /// <summary>
        ///   Copies the properties of the data transfer object to the specified table column.
        /// </summary>
        /// <param name="column">The table column.</param>
        /// <exception cref="ArgumentNullException">Thrown when the value of <paramref name="column"/> is null.</exception>
        public abstract void CopyTo(Column column);
    }
}
